package core

import (
	"leaf/core/cluster"
	"leaf/core/conf"
	"leaf/core/console"
	"leaf/core/event"
	"leaf/core/log"
	"leaf/core/rpc"
	"os/signal"
	"syscall"

	//"leaf/core/rpcx"
	"fmt"
	"leaf/core/service"
	"leaf/core/tool"
	"os"
	"strings"
)

var closeSig = make(chan bool, 1)

func Init(path string, tmap map[int32]string) func() {
	conf.LoadConfig(path, tmap)
	tool.SetGoDebug(conf.Config.GoDebug)
	index := strings.LastIndex(path, "/")
	if index >= 0 {
		path = path[index+1:]
	}
	path = strings.TrimSuffix(path, ".json")
	args := strings.Split(path, "_")
	if len(args) == 2 {
		conf.Config.LogHeader = args[0]
		conf.Config.ServerId = int32(tool.Atoi(args[1]))
		conf.Config.ServerType = conf.Config.ServerId / 1000
	}
	return initLogger()
}

func initLogger() func() {
	if conf.Config.LogLevel != "" {
		if conf.Config.LogPath != "" {
			os.MkdirAll(conf.Config.LogPath, os.ModePerm)
		}
		if conf.Config.LogMaxSize <= 0 {
			conf.Config.LogMaxSize = 30
		}
		logHeader := fmt.Sprintf("%v_%v", conf.Config.LogHeader, conf.Config.ServerId)
		logger, err := log.New(conf.Config.LogLevel, conf.Config.LogPath, logHeader, conf.Config.LogMaxSize, conf.Config.LogFlag)
		if err != nil {
			panic(err)
		}
		log.Export(logger)

		return func() {
			logger.Close()
		}
	}
	return nil
}

func Run(servs ...service.IService) {
	//Runing
	log.Release("core %v starting up", version)
	// module
	for i := 0; i < len(servs); i++ {
		service.Register(servs[i])
		//rpcx.Register(servs[i])
		rpc.RegisterService(servs[i])
	}
	// cluster
	cluster.Init()
	// IService Init
	service.Init(closeSig)
	// IService run
	service.Start()
	// cluster
	cluster.Start()
	// console
	console.Start()

	event.EventNotify(event.EventId_Leaf_Run, nil)
	// close
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP)
	sig := <-c
	log.Release("core closing down signal: %v", sig)

	//Sleep(10000)
	// go close
	log.Release("core go close")
	tool.GoClose()
	// console
	console.Destroy()
	// cluster
	cluster.Destroy()
	// IService
	service.Destroy()
	//go wait
	tool.GoWait()
}
